/*
 * @Author: hfWang
 * @Date: 2022-12-07 20:18:15
 * @LastEditTime: 2022-12-21 13:21:25
 * @Description: file content
 * @FilePath: \tmt-web\src\components\common\LfFlowChart\index.tsx
 */
import React, { FC, useEffect, useRef, useState } from 'react';

import LogicFlow, { RegisterConfig } from '@logicflow/core';
import '@logicflow/core/dist/style/index.css';
import '@logicflow/extension/lib/style/index.css';

import { ConfigProvider } from 'antd';
import './index.less';

import CtrlBar from './components/CtrlBar';
import EditBar from './components/EditBar';
import SideBar from './components/SideBar';
import baseNodesAndEdges from './node';

import { LfFlowChartExport, LfFlowChartProps } from './types';
import { useLfConfig } from './utils/config';
import { lf_box_style } from './utils/contants';
import { useFlowChart } from './utils/hooks';

/**
 * 流程图
 */
const LfFlowChart: FC<LfFlowChartProps> = (props) => {
  const lfRef = useRef<HTMLDivElement | null>(null);
  const lfBoxRef = useRef<HTMLDivElement | null>(null);
  const lf = useRef<LogicFlow | null>(null);
  const { ctrlBar = true } = props;

  const [showSideBar, setShowSideBar] = useState<boolean>(ctrlBar); // 是否显示拖拽面板

  const { getLfConfig, extensionList, baseNodesAndEdgesList } = useLfConfig();

  const {
    saveFlowChartInfo,
    lfZoomInOrOut,
    openMiniMap,
    dragInNode,
    lfUndoOrRedo,
    selectMoreNode,
    stylesChange,
    setZIndex,
    onChangeUndoOrRedo,
    getSelectNodeOrEdgeStyles,
    openSelectMore,
    theme,
    activeEdges,
    activeNodes,
    properties,
  } = useFlowChart(props, {
    lf,
    lfBoxRef,
  });

  // 注册插件
  const registerExtenSion = () => {
    extensionList.forEach((extension) => {
      LogicFlow.use(extension);
    });
  };

  // 注册自定义节点
  const registerCustomNode = () => {
    const allNodeList: RegisterConfig[] = props.nodeList
      ? [...baseNodesAndEdgesList, ...props.nodeList]
      : baseNodesAndEdgesList;
    allNodeList.forEach((node) => (lf.current as LogicFlow).register(node));
  };

  useEffect(() => {
    // 插件注册必须在实例化之前
    registerExtenSion();

    lf.current = new LogicFlow({
      container: lfRef.current as HTMLDivElement,
      ...getLfConfig(props.config),
    });

    // 节点注册必须在实例化之后
    registerCustomNode();

    const { data = {} } = props;
    // 流程图渲染
    lf.current.render(data);

    // 监听操作变化
    lf.current.on('history:change', onChangeUndoOrRedo);

    // 监听 画布框选、节点点击，空白处点击，节点连线点击
    lf.current.on(
      'selection:selected,node:click,blank:click,edge:click',
      getSelectNodeOrEdgeStyles,
    );

    return () => {
      if (lf.current !== null) {
        lf.current = null;
      }
    };
  }, []);

  useEffect(() => {
    if (lf.current) {
      const { editConfigModel } = (lf.current as LogicFlow).graphModel;
      editConfigModel.updateEditConfig({
        // 设置是否为静默模式
        isSilentMode: props.disable || false,
      });
    }
  }, [props.disable, lf]);

  return (
    <ConfigProvider
      theme={{
        token: {
          colorPrimary: theme,
        },
      }}
    >
      <div
        className={`rt-libs-lf-flow-chart ${props?.className}`}
        style={lf_box_style}
        ref={lfBoxRef}
      >
        <div ref={lfRef}></div>
        {!props.disable && (
          <>
            {/* 拖拽面板 */}
            {showSideBar && (
              <SideBar
                dragInNode={dragInNode}
                height={props.config.height}
                style={props.styleConf?.sideBarCss}
              />
            )}
            {/* 编辑面板 */}
            {(activeNodes.length > 0 || activeEdges.length > 0) && (
              <EditBar
                height={props.config.height}
                style={props.styleConf?.editBarCss}
                elementsStyle={properties}
                setZIndex={setZIndex}
                onlyEdge={activeNodes.length === 0 && activeEdges.length > 0}
                onChange={stylesChange}
              ></EditBar>
            )}
            {/* 控制面板 */}
            {ctrlBar && (
              <CtrlBar
                style={props.styleConf?.ctrlBarCss}
                showSideBar={showSideBar}
                selectMore={openSelectMore}
                openMiniMap={openMiniMap}
                toggleSidebar={() => setShowSideBar(!showSideBar)}
                selectMoreNode={selectMoreNode}
                lfZoomInOrOut={lfZoomInOrOut}
                lfUndoOrRedo={lfUndoOrRedo}
                saveFlowChartInfo={saveFlowChartInfo}
              ></CtrlBar>
            )}
          </>
        )}
      </div>
    </ConfigProvider>
  );
};

export default {
  LfFlowChart,
  baseNodesAndEdges,
} as LfFlowChartExport;
